__author__ = "kiana";

import random;
from data_process.dcb_data_process import *;
from statsmodels.tsa.api import SimpleExpSmoothing;
from statsmodels.tsa.api import Holt;
from data_process.LSTM_Model import *;

'''
双色球预测
'''

# 添加双色球池
'''
添加双色球池
l：双色球池子，最终长度 7 位
num：添加的数值
red_ball：对否红球
'''
def add_ball_pool(l=[], num=0, red_ball=True):
    min = 1;
    max = 33 if red_ball else 16;
    if red_ball and num >= min and num <= max and not l.__contains__(num):
        # 如果是红球，添加的值满足[1, 33]，并且不能重复
        l.append(num);
        l.sort();
        return l;
    elif not red_ball and num >= min and num <= max:
        # 如果不是红球，添加的值满足[1, 16]
        l.append(num);
        return l;
    else:
        # 不满足以上条件，则递归调用自身，直到添加成功为止
        add_ball_pool(l, random.randint(min, max), red_ball);

# 随机预测
def get_random_forecast():
    l = [];
    # 循环 7 次，填充完双色球 list
    for i in range(1, 8):
        red_ball = True if i < 7 else False;
        min = 1;
        max = 33 if red_ball else 16;
        num = random.randint(min, max);
        add_ball_pool(l, num, red_ball);
    return l;

'''
平滑指数预测，ses，通过加权平均值计算出预测值
获取每个位置所有数据，交给预测模型，进行模型训练，将训练好的模型预测下一个数字，将该数字添加到球池里面，形成最终结果
'''
def get_ses_forecast(df):
    l = [];
    for i in range(1, 8):
        key = "red_ball%d" % i if i < 7 else "blue_ball";
        data = df[key].map(lambda item:int(item));
        # print(data.tolist());

        # 传入历史数据集，设置权重值（0 - 1），训练出适应模型
        fit_model = SimpleExpSmoothing(data.tolist()).fit(
            smoothing_level=random.randint(1, 10) / 10,
            optimized=False
        );
        # 用适应模型预测数据，返回数组 [3.98919522]
        predict = fit_model.predict();

        # 将预测的结果添加到球池中
        red_ball = True if i < 7 else False;
        num = round(predict[0]);
        add_ball_pool(l, num, red_ball);
    return l;

'''
霍尔特预测：将数据及分解为几个组成部分：趋势 Trend，季节性 Seasonal 和残差 Residual，这里示例线性趋势
获取每个位置所有数据，交给预测模型，进行模型训练，将训练好的模型预测下一个数字，将该数字添加到球池里面，形成最终结果
'''
def get_holt_forecast(df):
    l = [];
    for i in range(1, 8):
        key = "red_ball%d" % i if i < 7 else "blue_ball";
        data = df[key].map(lambda item:int(item));
        # print(data.tolist());

        # 传入历史数据集，设置权重值（0 - 1），训练出适应模型
        fit_model = Holt(data.tolist()).fit(
            smoothing_level=random.randint(1, 10) / 10,
            smoothing_trend=random.randint(1, 10) / 10,
            optimized=False
        );
        # 用适应模型预测数据，返回数组 [3.98919522]
        predict = fit_model.predict();

        # 将预测的结果添加到球池中
        red_ball = True if i < 7 else False;
        num = round(predict[0]);
        add_ball_pool(l, num, red_ball);
    return l;

'''
LSTM 神经网络预测
获取每个位置所有数据，交给预测模型，进行模型训练，将训练好的模型预测下一个数字，将该数字添加到球池里面，形成最终结果
'''
def get_lstm_forecast(df):
    l = [];
    for i in range(1, 8):
        key = "red_ball%d" % i if i < 7 else "blue_ball";
        # data = df[key].map(lambda item:int(item));
        data = np.asarray(df[key].map(lambda item: int(item)));

        lstm = LSTM_Model(data=data, step_length=3);
        lstm.application();
        predict = lstm.predict;

        # 将预测的结果添加到球池中
        red_ball = True if i < 7 else False;
        num = round(predict[0]);
        add_ball_pool(l, num, red_ball);
    return l;

if __name__ == '__main__':
    random_list = get_random_forecast();
    print("随机预测结果：%s" % random_list);
    df = init_dcb_df_data(get_all_dcb());
    ses_list = get_ses_forecast(df);
    print("平滑指数预测结果：%s" % ses_list);
    holt_list = get_holt_forecast(df);
    print("霍尔特预测结果：%s" % holt_list);
    lstm_list = get_lstm_forecast(df);
    print("lstm预测结果：%s" % lstm_list);
